home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / jaq / dist / asaca.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-01  |  13.1 KB  |  598 lines

  1. /*
  2.  * 
  3.  * Copyright (c) 1988 Regents of the University of California
  4.  * 
  5.  * Permission to use, copy, modify, and distribute this software and its
  6.  * documentation for educational, research, and non-profit purposes and
  7.  * without fee is hereby granted, provided that the above copyright
  8.  * notice appear in all copies and that both that copyright notice and
  9.  * this permission notice appear in supporting documentation, and that
  10.  * the name of the University of California not be used in advertising
  11.  * or publicity pertaining to distribution of the software without
  12.  * specific, written prior permission.  Permission to incorporate this
  13.  * software into commercial products can be obtained from the Campus
  14.  * Software Office, 295 Evans Hall, University of California, Berkeley,
  15.  * Ca., 94720 provided only that the the requestor give the University
  16.  * of California a free licence to any derived software for educational
  17.  * and research purposes.  The University of California makes no
  18.  * representations about the suitability of this software for any
  19.  * purpose.  It is provided "as is" without express or implied warranty.
  20.  * 
  21.  */
  22.  
  23. /*
  24.  * ASACA (Metrum RSS-600) device driver. (User-level). Sends robot
  25.  * control signals over RS-232 port and interprets results. Driver
  26.  * provides a "slot-number" interface to the RSS-600 with slots
  27.  * 0 ... 599 corresponding to the drum bins (which store tapes) and
  28.  * slots 600 ... 604 corresponding to tape readers, or VLDS's.
  29.  */
  30.  
  31. #include "asaca.h"
  32.  
  33. int as_debug = 1;
  34.  
  35. /*
  36.  * asaca_open() is just a wrapper around the standard UNIX open system
  37.  * call. Open the ASACA device, set termio characteristics
  38.  */
  39. asaca_open (path)
  40.     char *path;
  41. {
  42.     int fdes;
  43.  
  44.     if ((fdes = open (path, O_RDWR|O_BLKANDSET)) < 0)
  45.         return (-1);
  46.  
  47.     if (ioctl (fdes, TCSETA, &asaca_tio) < 0) {
  48.         asaca_close (fdes);
  49.         return (-1);
  50.     }
  51.     return (fdes);
  52. }
  53.  
  54. /*
  55.  * asaca_close() simply closes the device. May need to do other things
  56.  * here prior to closing as we gain experience...
  57.  */
  58. asaca_close (fdes)
  59.     int fdes;
  60. {
  61.     return (close (fdes));
  62. }
  63.  
  64. /*
  65.  * asaca_write() simply does a character-by-character write to the ASACA
  66.  * device returned by asaca_open(). Returns #bytes actually written or
  67.  * failure
  68.  */
  69. asaca_write (fdes, buf, nbytes)
  70.     int fdes;
  71.     caddr_t buf;
  72.     int nbytes;
  73. {
  74.     register int i = 0;
  75.  
  76.     while ((*buf != '\0') && i < nbytes) {
  77.         if (write (fdes, buf, 1) != 1)
  78.                 return (-1);
  79.         buf++; i++;
  80.     }
  81.     return (i);
  82. }
  83.  
  84. /*
  85.  * asaca_read() does a character-by-character read of the ASACA device
  86.  * until a terminating '>' is read. Returns #bytes actually read or
  87.  * failure
  88.  */
  89. asaca_read (fdes, buf, nbytes)
  90.     int fdes;
  91.     caddr_t buf;
  92.     int nbytes;
  93. {
  94.     register int i = 0;
  95.  
  96.     while (i < nbytes) {
  97.         switch (read (fdes, buf, 1)) {
  98.         case    1:
  99.             i++;
  100.             if (*buf++ == ASTERM) {
  101.                 *buf = '\0';
  102.                 return (i);
  103.             }
  104.             break;
  105.         case    0:
  106.             *buf = '\0';
  107.             return (i);
  108.         default:
  109.             return (-1);
  110.         }
  111.     }
  112.     return (0);
  113. }
  114.  
  115. /*
  116.  * asaca_ioctl() issues asaca commands over tty line. Code compatible with
  117.  * standard UNIX ioctl kernel code with future migration to kernel-mode
  118.  * in mind.
  119.  */
  120. asaca_ioctl (fdes, cmd, data)
  121.     int     fdes;
  122.     int    cmd;
  123.     caddr_t    *data;
  124. {
  125.     register struct    ascmd *dp;
  126.     register char *bp;
  127.     register int len;
  128.     char buf[BUFSIZ];
  129.  
  130.     if ((cmd&_IOC_IN) || (cmd&_IOC_OUT))
  131.         dp = (struct ascmd *)data;
  132.  
  133.     switch (cmd) {
  134.     case    ASIOCALRMON:
  135.     case    ASIOCALRMOFF:
  136.         switch (dp->as_mode) {
  137.         case    0:
  138.             sprintf (buf, "O%c***%c>", unittocmd(cmd), ASALRMALL);
  139.             break;
  140.         case    1:
  141.             sprintf (buf, "O%c***%c>", unittocmd(cmd), ASALRM1);
  142.             break;
  143.         case    2:
  144.             sprintf (buf, "O%c***%c>", unittocmd(cmd), ASALRM2);
  145.             break;
  146.         case    3:
  147.             sprintf (buf, "O%c***%c>", unittocmd(cmd), ASALRM3);
  148.             break;
  149.         default:
  150.             goto bad;
  151.         }
  152.         break;
  153.  
  154.     case    ASIOCLOAD2:
  155.     case    ASIOCSTORE2:
  156.         if (isbin(dp->as_bin) && isvlds(dp->as_vlds)) {
  157.             sprintf (buf, "O%c%c%02d%cD%13s>", unittocmd(cmd),
  158.               unittoface(dp->as_bin), unittobin(dp->as_bin),
  159.               unittovlds(dp->as_vlds), dp->as_barcode);
  160.         } else {
  161.             goto bad;
  162.         }
  163.         break;
  164.  
  165.     case    ASIOCLOAD1:
  166.     case    ASIOCSTORE1:
  167.         if (isbin(dp->as_bin) && isvlds(dp->as_vlds)) {
  168.             sprintf (buf, "O%c%c%02d%c>", unittocmd(cmd),
  169.               unittoface(dp->as_bin), unittobin(dp->as_bin),
  170.               unittovlds(dp->as_vlds));
  171.         } else {
  172.             goto bad;
  173.         }
  174.         break;
  175.  
  176.     case    ASIOCBCREAD2:
  177.  
  178.         /*
  179.          * XXX - Only two operations for single-cassette barcode
  180.          * reads are supported: 
  181.          *    - read barcode of tape in a slot
  182.          *    - read barcode of tape in a VLDS
  183.          */
  184.         if (isbin(dp->as_src)) {
  185.             sprintf (buf, "O%c%c%02d*>", unittocmd(cmd),
  186.               unittoface(dp->as_src), unittobin(dp->as_src));
  187.         } else {
  188.             if (isvlds(dp->as_src)) {
  189.                 sprintf (buf, "O%c30%c*>", unittocmd(cmd),
  190.                      unittovlds(dp->as_src));
  191.             } else {
  192.                 goto bad;
  193.             }
  194.         }
  195.         break;
  196.  
  197.     case    ASIOCINIT:
  198.     case    ASIOCEJECT:
  199.     case    ASIOCINJECT:
  200.     case    ASIOCDOOROPEN:
  201.     case    ASIOCSENSE:
  202.         sprintf (buf, "O%c****>", unittocmd(cmd));
  203.         break;
  204.  
  205.     case    ASIOCDRUMSET:
  206.         if (isbin(dp->as_bin)) {
  207.             sprintf (buf, "O%c%c***>", unittocmd(cmd),
  208.                  unittoface(dp->as_bin));
  209.         } else {
  210.             goto bad;
  211.         }
  212.         break;
  213.  
  214.     case    ASIOCFIPDISP:
  215.         if (isvlds(dp->as_vlds)) {
  216.             sprintf (buf, "O%c***%cB%13s>", unittocmd(cmd),
  217.                  unittovlds(dp->as_vlds), dp->as_barcode);
  218.         } else {
  219.             goto bad;
  220.         }
  221.         break;
  222.  
  223.     case    ASIOCSIDEIND:
  224.         if (isbin(dp->as_bin)) {
  225.             switch (dp->as_mode) {
  226.             case    0:
  227.                 sprintf (buf, "O%c2%02d%c>", unittocmd(cmd),
  228.                      unittobin(dp->as_bin), ASON);
  229.                 break;
  230.             case    1:
  231.                 sprintf (buf, "O%c2%02d%c>", unittocmd(cmd),
  232.                      unittobin(dp->as_bin), ASOFF);
  233.                 break;
  234.             default:
  235.                 goto bad;
  236.             }
  237.         } else {
  238.             goto bad;
  239.         }
  240.         break;
  241.  
  242.     case    ASIOCDETECT:
  243.  
  244.         /*
  245.          * Metrum only supports cassette detect for the right
  246.          * side drum. (drum faces 'G' - 'L'). User should
  247.          * issue "DETECT" command only for slots 300 - 599.
  248.          */
  249.         if (isbin(dp->as_bin) && (unittoface(dp->as_bin) > 'F')) {
  250.             sprintf (buf, "O%c%c%02d*>", unittocmd(cmd),
  251.                  unittoface(dp->as_bin),
  252.                  dp->as_mode == 0 ? 0 :
  253.                  unittobin(dp->as_bin));
  254.         } else {
  255.             goto bad;
  256.         }
  257.         break;
  258.  
  259.     case    ASIOCMANUAL:
  260.         switch (dp->as_mode) {
  261.         case    0:
  262.             sprintf (buf, "O%c%c***>", unittocmd(cmd), ASON);
  263.             break;
  264.         case    1:
  265.             sprintf (buf, "O%c%c***>", unittocmd(cmd), ASOFF);
  266.             break;
  267.         default:
  268.             goto bad;
  269.         }
  270.         break;
  271.  
  272.     case    ASIOCDOORLOCK:
  273.         switch (dp->as_mode) {
  274.         case    0:
  275.             sprintf (buf, "O%c%c***>", unittocmd(cmd), ASUNLOCK);
  276.             break;
  277.         case    1:
  278.             sprintf (buf, "O%c%c***>", unittocmd(cmd), ASLOCK);
  279.             break;
  280.         default:
  281.             goto bad;
  282.         }
  283.         break;
  284.  
  285.     case    ASIOCMOVE1:
  286.         if (isvlds(dp->as_src) && isvlds(dp->as_dest)) {
  287.             sprintf (buf, "O%c%c%c**>", unittocmd(cmd),
  288.                  unittovlds(dp->as_src),
  289.                  unittovlds(dp->as_dest));
  290.         } else {
  291.             goto bad;
  292.         }
  293.         break;
  294.  
  295.     case    ASIOCMOVE2:
  296.         if (isbin(dp->as_src) && isbin(dp->as_dest)) {
  297.             switch (dp->as_mode) {
  298.             case    0:
  299.                 sprintf (buf, "O%c%c%02d%cQ%c%02d%13s>",
  300.                      unittocmd(cmd), unittoface(dp->as_src),
  301.                      unittobin(dp->as_src), ASBARCHK,
  302.                      unittoface(dp->as_dest),
  303.                      unittobin(dp->as_dest),
  304.                      dp->as_barcode);
  305.                 break;
  306.             case    1:
  307.                 sprintf (buf, "O%c%c%02d%cQ%c%02d%13s>",
  308.                      unittocmd(cmd), unittoface(dp->as_src),
  309.                      unittobin(dp->as_src), ASNOBARCHK,
  310.                      unittoface(dp->as_dest),
  311.                      unittobin(dp->as_dest),
  312.                      "*************");
  313.                 break;
  314.             default:
  315.                 goto bad;
  316.             }
  317.         } else {
  318.             goto bad;
  319.         }
  320.         break;
  321.  
  322.     case    ASIOCMVHDLR:
  323.     case    ASIOCMOVE3:
  324.         if (isbin(dp->as_dest)) {
  325.             sprintf (buf, "O%c%c%02d*>", unittocmd(ASIOCMOVE3),
  326.                  unittoface(dp->as_dest),
  327.                  unittobin(dp->as_dest));
  328.         } else {
  329.             if (isvlds(dp->as_dest)) {
  330.                 sprintf (buf, "O%c%c01*>",
  331.                      unittocmd(ASIOCMOVE3),
  332.                          unittovlds(dp->as_dest));
  333.             } else {
  334.                 goto bad;
  335.             }
  336.         }
  337.         break;
  338.  
  339.     case    ASIOCMVTAPE:
  340.         /*
  341.          * Generic tape move command; no barcode checks. Provides
  342.          * cleaner, more natural interface to applications. Code is
  343.          * redundant as h*ll, but works...
  344.          */
  345.         if ((!isbin(dp->as_src) && !isvlds(dp->as_src)) ||
  346.             (!isbin(dp->as_dest) && !isvlds(dp->as_dest)))
  347.             goto bad;
  348.  
  349.         if (isbin(dp->as_src) && isbin(dp->as_dest)) {
  350.             /*
  351.              * Same as MOVE2 with no barcode check...
  352.              */
  353.             sprintf (buf, "O%c%c%02d%cQ%c%02d%13s>",
  354.                  unittocmd(ASIOCMOVE2),
  355.                  unittoface(dp->as_src),
  356.                  unittobin(dp->as_src), ASNOBARCHK,
  357.                  unittoface(dp->as_dest),
  358.                  unittobin(dp->as_dest),
  359.                  "*************");
  360.             break;
  361.         }
  362.  
  363.         if (isbin(dp->as_src) && isvlds(dp->as_dest)) {
  364.             /* 
  365.              * Same as LOAD1...
  366.              */
  367.             sprintf (buf, "O%c%c%02d%c>",
  368.                  unittocmd(ASIOCLOAD1),
  369.                  unittoface(dp->as_src),
  370.                  unittobin(dp->as_src),
  371.                  unittovlds(dp->as_dest));
  372.             break;
  373.         }
  374.  
  375.         if (isvlds(dp->as_src) && isbin(dp->as_dest)) {
  376.             /*
  377.              * Same as STORE1...
  378.              */
  379.             sprintf (buf, "O%c%c%02d%c>",
  380.                  unittocmd(ASIOCSTORE1),
  381.                  unittoface(dp->as_dest),
  382.                  unittobin(dp->as_dest),
  383.                  unittovlds(dp->as_src));
  384.             break;
  385.         }
  386.  
  387.         if (isvlds(dp->as_src) && isvlds(dp->as_dest)) {
  388.             /* 
  389.              * Same as MOVE1...
  390.              */
  391.             sprintf (buf, "O%c%c%c**>", unittocmd(ASIOCMOVE1),
  392.                  unittovlds(dp->as_src),
  393.                  unittovlds(dp->as_dest));
  394.             break;
  395.         }
  396.  
  397.     case    ASIOCMVTAPE_BC:
  398.         /*
  399.          * Generic tape move with barcode checks
  400.          */
  401.         if ((!isbin(dp->as_src) && !isvlds(dp->as_src)) ||
  402.             (!isbin(dp->as_dest) && !isvlds(dp->as_dest)))
  403.             goto bad;
  404.  
  405.         if (isbin(dp->as_src) && isbin(dp->as_dest)) {
  406.             /*
  407.              * Same as MOVE2 with barcode check...
  408.              */
  409.             sprintf (buf, "O%c%c%02d%cQ%c%02d%13s>",
  410.                  unittocmd(ASIOCMOVE2),
  411.                  unittoface(dp->as_src),
  412.                  unittobin(dp->as_src), ASBARCHK,
  413.                  unittoface(dp->as_dest),
  414.                  unittobin(dp->as_dest),
  415.                  dp->as_barcode);
  416.             break;
  417.         }
  418.  
  419.         if (isbin(dp->as_src) && isvlds(dp->as_dest)) {
  420.             /* 
  421.              * Same as LOAD2...
  422.              */
  423.             sprintf (buf, "O%c%c%02d%cD%13s>",
  424.                  unittocmd(ASIOCLOAD2),
  425.                  unittoface(dp->as_src),
  426.                  unittobin(dp->as_src),
  427.                  unittovlds(dp->as_dest),
  428.                  dp->as_barcode);
  429.             break;
  430.         }
  431.  
  432.         if (isvlds(dp->as_src) && isbin(dp->as_dest)) {
  433.             /*
  434.              * Same as STORE2...
  435.              */
  436.             sprintf (buf, "O%c%c%02d%cD%13s>",
  437.                  unittocmd(ASIOCSTORE2),
  438.                  unittoface(dp->as_dest),
  439.                  unittobin(dp->as_dest),
  440.                  unittovlds(dp->as_src),
  441.                  dp->as_barcode);
  442.             break;
  443.         }
  444.  
  445.         if (isvlds(dp->as_src) && isvlds(dp->as_dest)) {
  446.             /*
  447.              * MOVE1 doesn't support barcode checking
  448.              */
  449.             goto bad;
  450.         }
  451.         
  452.     case    ASIOCBCREAD1:
  453.     case    ASIOCBCRS:
  454.         /*
  455.          * XXX - Bar Code Read Command 1 (of 50 tapes) and
  456.          * associated Bar Code Read Stop Command not supported
  457.          */
  458.     default:
  459.         goto bad;
  460.     }
  461.  
  462.     /*
  463.      * issue command to ASACA and wait for completion code.
  464.      */
  465.     len = strlen(buf);
  466.     if ((asaca_write (fdes, buf, len)) != len) {
  467.         /* errno set by "asaca_write" */
  468.         return (-1);
  469.     }
  470.  
  471.     if (!(cmd&_IOC_OUT)) {
  472.         /* No answer generated for these; return success */
  473.         return (0);
  474.     }
  475.  
  476.     if (cmd == ASIOCBCREAD2) {
  477.         /* Give bar code read extra time to complete */
  478.         sleep (1);
  479.     }
  480.  
  481.     /*
  482.      * Read ASACA command response. Response will be of
  483.      * the form: "Oxy>", where 'x' is a command completion
  484.      * code flag and 'y' is zero or more additional char's,
  485.      * making "len" at least three in normal cases
  486.      */
  487.     if ((len = asaca_read(fdes, buf, BUFSIZ)) < 3) {
  488.         /* errno set by "asaca_read" */
  489.         return (-1);
  490.     }
  491.         
  492.     if ((buf[0] != ASHDR) || (buf[len - 1] != ASTERM)) {
  493.         /* mal-formed response; this should never happen */
  494.         goto bad;
  495.     }
  496.         
  497.     switch (buf[1]) {
  498.     case    'D':
  499.     case    'F':
  500.     case    'K':
  501.     case    'V':
  502.         /* Normal operation answer */
  503.         dp->as_error = AS_ENOERR;
  504.         break;
  505.     case    'H':
  506.         /* Barcode read return */
  507.         dp->as_error = AS_ENOERR;
  508.         bcopy (&buf[5], dp->as_barcode, 13);
  509.         break;
  510.     case    'S':
  511.         /* Door sense return */
  512.         dp->as_error = AS_ENOERR;
  513.         bcopy (&buf[2], dp->as_sense, 3);
  514.         break;
  515.     case    'W':
  516.         /* Cassette detect return */
  517.         dp->as_error = AS_ENOERR;
  518.         bcopy (&buf[5], dp->as_sense, 1);
  519.         break;
  520.     case    'B':
  521.         /* Barcode mismatch warning */
  522.         dp->as_error = AS_EWARN;
  523.         bcopy (&buf[2], dp->as_barcode, 13);
  524.         if (as_debug)
  525.             printf ("asaca: Barcode mismatched\n");
  526.         break;
  527.     case    'E':
  528.         /* Barcode read failure */
  529.         dp->as_error = AS_EWARN;
  530.         if (as_debug)
  531.             printf ("asaca: Barcode read failure\n");
  532.         break;
  533.     case    'N':
  534.         /* Error without operational interrupt */
  535.         dp->as_error = AS_EWARN;
  536.         if (as_debug) {
  537.             switch (buf[2]) {
  538.             case    '1':
  539.                 printf ("asaca: Volume was not grabbed\n");
  540.                 break;
  541.             case    '2':
  542.                 printf ("asaca: Volume was not loaded\n");
  543.                 break;
  544.             case    '3':
  545.                 printf ("asaca: Right door is open\n");
  546.                 break;
  547.             case    '4':
  548.                 printf ("asaca: Front door is open\n");
  549.                 break;
  550.             case    '5':
  551.                 printf ("asaca: Volume is protruding from one of the bins\n");
  552.                 break;
  553.             case    '6':
  554.                 printf ("asaca: I/O failure\n");
  555.                 break;
  556.             default:
  557.                 printf ("asaca: Unknown warning\n");
  558.             }
  559.         }
  560.         break;
  561.  
  562.     case    'G':
  563.         /* Error with operational Interrupt */
  564.         dp->as_error = AS_EFATAL;
  565.         switch (buf[2]) {
  566.         case    '1':
  567.             printf ("asaca: Right drum failure\n");
  568.             break;
  569.         case    '2':
  570.             printf ("asaca: Left drum failure\n");
  571.             break;
  572.         case    '3':
  573.             printf ("asaca: Elevator failure in the x axis\n");
  574.             break;
  575.         case    '4':
  576.             printf ("asaca: Handler failure in the y axis\n");
  577.             break;
  578.         case    '5':
  579.             printf ("asaca: Handler failure in the z axis\n");
  580.             break;
  581.         case    '6':
  582.             printf ("asaca: Hardware error\n");
  583.             break;
  584.         case    '7':
  585.             printf ("asaca: Command error, RTS 2 second failure\n");
  586.             break;
  587.         default:
  588.             printf ("asaca: Unknown fatal error\n");
  589.         }
  590.     }
  591.  
  592. done:
  593.     return (0);
  594. bad:
  595.     errno = EINVAL;
  596.     return (-1);
  597. }
  598.